﻿
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using Autofac;
using Common.Commands;
using fc2editor.Common;
using fc2editor.DataModel;
using fc2editor.Services;
using fc2editor.Utils;
namespace fc2editor.ViewModels
{
    public class MainViewModel : ViewModelBase
    {
        #region Properties

        public ObservableCollection<Aircraft> Aircrafts
        {
            get
            {
                return aircrafts;
            }
            private set
            {
                aircrafts = value;
                NotifyPropertyChanged(() => Aircrafts);
            }
        }

        public Aircraft SelectedAircraft
        {
            get
            {
                return selectedAircraft;
            }
            set
            {
                selectedAircraft = value;
                NotifyPropertyChanged(() => SelectedAircraft);

                UpdateAircraftImage();
            }
        }

        public byte[] AircraftImage
        {
            get
            {
                return aircraftImage;
            }
            private set
            {
                aircraftImage = value;
                NotifyPropertyChanged(() => AircraftImage);
            }
        }

        public ObservableCollection<Weapon> Weapons
        {
            get
            {
                return weapons;
            }
            private set
            {
                weapons = value;
                NotifyPropertyChanged(() => Weapons);
            }
        }

        public List<WeaponsCategory> WeaponCategories
        {
            get
            {
                return weaponCategories;
            }
            set
            {
                weaponCategories = value;
                NotifyPropertyChanged(() => WeaponCategories);
            }
        }

        public WeaponsCategory SelectedCategory
        {
            get
            {
                return selectedCategory;
            }
            set
            {
                selectedCategory = value;
                NotifyPropertyChanged(() => SelectedCategory);

                UpdateWeaponsCategoryFilter();
            }
        }

        public string WeaponsCategoryFilter
        {
            get
            {
                return weaponsCategoryFilter;
            }
            set
            {
                weaponsCategoryFilter = value;
                NotifyPropertyChanged(() => WeaponsCategoryFilter);

                UpdateWeaponsCategoryFilter();
            }
        }

        public Weapon SelectedWeapon
        {
            get
            {
                return selectedWeapon;
            }
            set
            {
                selectedWeapon = value;
                NotifyPropertyChanged(() => SelectedWeapon);
            }
        }

        public IWeaponSelectorViewModel WeaponSelectorViewModel
        {
            get
            {
                return weaponSelectorViewModel;
            }
            private set
            {
                weaponSelectorViewModel = value;
                NotifyPropertyChanged(() => WeaponSelectorViewModel);
            }
        }

        public DelegateCommand<object> ViewLoadedCommand { get; private set; }

        public DelegateCommand<object> PylonWeaponClickedCommand { get; private set; }

        public DelegateCommand<object> ModifyWeaponCommand { get; private set; }

        public DelegateCommand<object> RemoveWeaponCommand { get; private set; }

        public DelegateCommand<object> AppendWeaponAfterCommand { get; private set; }

        public DelegateCommand<object> SavePylonsCommand { get; private set; }

        public DelegateCommand<object> ResetPylonsCommand { get; private set; }

        public DelegateCommand<MouseMoveArgs> DragWeaponCommand { get; private set; }

        public DelegateCommand<object> WeaponDropCommand { get; private set; }

        #endregion

        public MainViewModel(Autofac.IContainer container)
        {
            weaponService = container.Resolve<IWeaponService>();
            aircraftService = container.Resolve<IAircraftService>();
            fileService = container.Resolve<IFileService>();

            WeaponSelectorViewModel = container.Resolve<IWeaponSelectorViewModel>();

            ViewLoadedCommand = new DelegateCommand<object>(OnViewLoadedCommand);
            PylonWeaponClickedCommand = new DelegateCommand<object>(OnPylonWeaponClickedCommand);
            ModifyWeaponCommand = new DelegateCommand<object>(OnModifyWeaponCommand);
            RemoveWeaponCommand = new DelegateCommand<object>(OnRemoveWeaponCommand);
            AppendWeaponAfterCommand = new DelegateCommand<object>(OnAppendWeaponAfterCommand);
            SavePylonsCommand = new DelegateCommand<object>(OnSavePylonsCommand);
            ResetPylonsCommand = new DelegateCommand<object>(OnResetPylonsCommand);
            DragWeaponCommand = new DelegateCommand<MouseMoveArgs>(OnDragWeaponCommand);
            WeaponDropCommand = new DelegateCommand<object>(OnWeaponDropCommand);
        }

        #region Private methods

        private void UpdateAircraftImage()
        {
            if (SelectedAircraft == null)
                return;

            AircraftImage = fileService.GetPicture(SelectedAircraft);
        }

        private void UpdateWeaponsCategoryFilter()
        {
            var viewSource = CollectionViewSource.GetDefaultView(Weapons);

            if (SelectedCategory == WeaponsCategory.Empty || SelectedCategory == null)
                viewSource.Filter = (w) =>
                {
                    var weapon = (Weapon)w;
                    return weapon.Name.Contains(WeaponsCategoryFilter);
                };
            else
            {
                viewSource.Filter = (w) =>
                {
                    var weapon = (Weapon)w;
                    return weapon.Category == SelectedCategory && weapon.Name.Contains(WeaponsCategoryFilter);
                };
            }
        }

        private void OnViewLoadedCommand(object parameter)
        {
            Aircrafts = aircraftService.GetAircrafts().ToObservableCollection();

            Weapons = weaponService.GetWeapons().ToObservableCollection();
            WeaponCategories = Weapons.Select(w => w.Category).
                Distinct(new WeaponsCategoryComparer()).ToList();
            WeaponCategories.Insert(0, WeaponsCategory.Empty);

            SelectInitialAircraft();
        }

        private void SelectInitialAircraft()
        {
            SelectedAircraft = Aircrafts.Where(a => a.Name == "MiG-29S").FirstOrDefault();
        }

        private void OnPylonWeaponClickedCommand(object parameter)
        {
        }

        private void OnModifyWeaponCommand(object parameter)
        {
            var weapon = GetUnderlyingWeapon(parameter);

            WeaponSelectorViewModel.Show((w) =>
            {
                ReplaceWeapon(weapon.Parent, weapon, w);
            });
        }

        private void ReplaceWeapon(Pylon pylon, Weapon oldWeapon, Weapon newWeapon)
        {
            if (pylon != null && oldWeapon != null && newWeapon != null)
            {
                pylon.ReplaceWeapon(oldWeapon, newWeapon);
            }
        }

        private void OnRemoveWeaponCommand(object parameter)
        {
            var weapon = GetUnderlyingWeapon(parameter);
            var pylon = weapon.Parent;
            pylon.RemoveWeapon(weapon);
        }

        private void OnResetPylonsCommand(object parameter)
        {
            if (SelectedAircraft == null)
                return;

            int index = Aircrafts.IndexOf(SelectedAircraft);
            var freshAircraft =
                aircraftService.ReloadAircraftByID(SelectedAircraft.ID);
            Aircrafts[index] = freshAircraft;
            SelectedAircraft = freshAircraft;
        }

        private void OnSavePylonsCommand(object parameter)
        {
            if (SelectedAircraft == null)
                return;

            fileService.SaveAircraft(SelectedAircraft);
        }

        private void OnAppendWeaponAfterCommand(object parameter)
        {
            var weapon = GetUnderlyingWeapon(parameter);
            var pylon = weapon.Parent;

            WeaponSelectorViewModel.Show((w) =>
            {
                if (!pylon.Weapons.Any(pw => pw.ID == w.ID))
                {
                    pylon.AddWeapon(w);
                }
            });
        }

        private void OnDragWeaponCommand(MouseMoveArgs parameter)
        {
            if (parameter == null)
                return;

            var dragSource = parameter.Sender as ListView;
            if (dragSource == null)
                return;

            //if (SelectedArtists == null)
            //    return;
            //if (SelectedArtists.Count < 1)
            //    return;

            if (parameter.Settings.LeftButton == MouseButtonState.Pressed)
            {
                DataObject dataObject = new DataObject(typeof(Weapon), SelectedWeapon);

                DragDrop.DoDragDrop(dragSource, dataObject, DragDropEffects.Copy);

                //// allow scroll inside listView
                //dragSource.SelectedItems.Clear();
                //SelectedArtists = null;
            }

        }

        private void OnWeaponDropCommand(object parameter)
        {
            var args = (DragArgs)parameter;
            var sender = args.Sender as FrameworkElement;
            if (sender != null && sender.DataContext is Weapon)
            {
                var pylonWeapon = sender.DataContext as Weapon;
                if (pylonWeapon.Parent != null)
                {
                    var pylon = pylonWeapon.Parent;
                    var newWeapon = args.Settings.Data.GetData(typeof(Weapon)) as Weapon;
                    if (newWeapon != null)
                    {
                        pylon.ReplaceWeapon(pylonWeapon, newWeapon);
                    }
                }
            }
        }

        private Weapon GetUnderlyingWeapon(object parameter)
        {
            var args = (MenuItemClickArgs)parameter;
            if (args != null && args.DataItem != null)
            {
                var item = args.DataItem as Weapon;
                return item;
            }

            return null;
        }

        #endregion

        #region Private fields

        private IAircraftService aircraftService;
        private IWeaponService weaponService;
        private IFileService fileService;

        private IWeaponSelectorViewModel weaponSelectorViewModel;

        private ObservableCollection<Aircraft> aircrafts;
        private ObservableCollection<Weapon> weapons;
        private List<WeaponsCategory> weaponCategories;
        private WeaponsCategory selectedCategory;
        private Aircraft selectedAircraft;
        private byte[] aircraftImage;
        private string weaponsCategoryFilter = String.Empty;
        private Weapon selectedWeapon;

        #endregion
    }
}
